package net.aiion.weave.impl.painters.stream.xhtml;

import net.aiion.weave.impl.painters.PaintBrushMessage;
import net.aiion.weave.impl.painters.stream.AbstractStreamBrush;
import net.aiion.weave.spi.messaging.annotations.Receives;
import net.aiion.weave.spi.naming.annotations.Bound;
import net.aiion.weave.spi.naming.annotations.Named;
import net.aiion.weave.spi.naming.annotations.NotScoped;
import net.aiion.weave.spi.painters.PaintBrush;
import net.aiion.weave.spi.painters.stream.xhtml.XhtmlPaintBrush;
import net.aiion.weave.spi.routing.Route;
import net.aiion.weave.spi.xml.XmlGenerator;
import net.aiion.weave.spi.xml.XmlQualifiedName;
import net.aiion.weave.spi.xml.XmlSinkFactory;
import net.aiion.weave.spi.xml.XmlSourceFactory;

@NotScoped
@Named
public class XhtmlPaintBrushImpl extends AbstractStreamBrush implements XhtmlPaintBrush
{
    private static final String HTML_EXTENSION = "html";
    private static final String XHTML_EXTENSION = "xhtml";

    private XmlGenerator xmlGenerator;

    public XhtmlPaintBrushImpl() {
    }

    @Bound
    public void initializePrintStream() {
        xmlGenerator = XmlSourceFactory.getInstance().createGenerator();
        xmlGenerator.addSink(XmlSinkFactory.getInstance().createWriter(getOutputStream()));
    }

    @Receives("net.aiion.weave.painters")
    public Object resolvePaintBrush(final PaintBrushMessage aPaintBrushMessage) {
        final Route route = aPaintBrushMessage.getRoute();
        if (HTML_EXTENSION.equals(route.getExtension()) || XHTML_EXTENSION.equals(route.getExtension())) {
            return this;
        }

        return null;
    }

    @Override
    public void paintBrush(final PaintBrush aPaintDevice) {
        ensureLastTagClosed();
        super.paintBrush(aPaintDevice);
    }

    @Override
    public void paintComponent(final Object aNamedInstance) {
        ensureLastTagClosed();
        super.paintComponent(aNamedInstance);
    }

    @Override
    public XmlQualifiedName createQualifiedName(final String aNamespaceURI, final String aLocalName) {
        return xmlGenerator.createQualifiedName(aNamespaceURI, aLocalName);
    }

    @Override
    public XmlQualifiedName createQualifiedName(final String aNamespaceURI, final String aLocalName,
        final String aPrefix)
    {
        return xmlGenerator.createQualifiedName(aNamespaceURI, aLocalName, aPrefix);
    }

    private void ensureLastTagClosed() {
        writeCharacters("");
    }

    @Override
    public void declareDocumentType(final int aDocumentTypeDeclarationId) {
        xmlGenerator.declareDocumentType(aDocumentTypeDeclarationId);
    }

    @Override
    public void declareDocumentType(final String aDocumentTypeDeclaration) {
        xmlGenerator.declareDocumentType(aDocumentTypeDeclaration);
    }

    @Override
    public void startElement(final String aLocalName) {
        xmlGenerator.startElement(aLocalName);
    }

    @Override
    public void startElement(final String aNamespaceURI, final String aLocalName) {
        xmlGenerator.startElement(aNamespaceURI, aLocalName);
    }

    @Override
    public void startElement(final String aNamespaceURI, final String aLocalName, final String aPrefix) {
        xmlGenerator.startElement(aNamespaceURI, aLocalName, aPrefix);
    }

    @Override
    public void startElement(final XmlQualifiedName aXmlQualifiedName) {
        xmlGenerator.startElement(aXmlQualifiedName);
    }

    @Override
    public void addAttribute(final String aLocalName, final String aValue) {
        xmlGenerator.addAttribute(aLocalName, aValue);
    }

    @Override
    public void addAttribute(final String aNamespaceURI, final String aLocalName, final String aValue) {
        xmlGenerator.addAttribute(aNamespaceURI, aLocalName, aValue);
    }

    @Override
    public void addAttribute(final String aNamespaceURI, final String aLocalName, final String aPrefix,
        final String aValue)
    {
        xmlGenerator.addAttribute(aNamespaceURI, aLocalName, aPrefix, aValue);
    }

    @Override
    public void addAttribute(final XmlQualifiedName aXmlQualifiedName, final String aValue) {
        xmlGenerator.addAttribute(aXmlQualifiedName, aValue);
    }

    @Override
    public void writeCharacters(final String aCharacters) {
        xmlGenerator.writeCharacters(aCharacters);
    }

    @Override
    public void writeCharacters(final String aCharacters, final int aCharactersDataType) {
        xmlGenerator.writeCharacters(aCharacters, aCharactersDataType);
    }

    @Override
    public void endElement() {
        xmlGenerator.endElement();
    }

    @Override
    public void closeBrush() {
    }
}
